/*
 * 
 */

package com.memorytech.starchive;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import jp.co.memory_tech.starchive.R;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.VideoView;

import com.memorytech.starchive.entity.FileInformation;
import com.memorytech.starchive.interfaceclass.OnProductDetailListener;
import com.memorytech.starchive.interfaceclass.OnVideoViewListener;
import android.view.GestureDetector.OnGestureListener;

// TODO: Auto-generated Javadoc
/**
 * The Class ProductDetail.
 * 
 * @author Tam-LT
 */
public class ProductDetail extends Fragment implements OnPreparedListener, OnErrorListener,
        OnVideoViewListener, OnGestureListener, OnTouchListener {

    /** The Constant ARG_POSITION. */
    final static String FILEINFOMATION = "position";
    private String tag = "ProductDetail";

    /** The file information. */
    private FileInformation fileInformation;

    /** Surface used to display video content. */
    private VideoView vv;

    /**
     * Flag indicates that particular file is ready to be played Flag is changed
     * to TRUE when onPrepared of VideoView is being called.
     */
    private boolean readyToPlay;

    /** CountDownTimer using for counting elapsed time of media file. */
    private CountDownTimer timer;

    /**
     * ProgressBar: - FIRST indicates the progress of media PLAYBACK (elapsed
     * time) - SECOND indicates the progress of media BUFFERING.
     */
    private ProgressBar progress;

    /** ProgressDialog shown while loading of the media file. */
    private ProgressDialog loading;

    /** The view. */
    private View view;

    /** The image view. */
    private ImageView imageView;

    /** The is full screen. */
    private boolean isFullScreen = false;

    /** The m callback. */
    OnProductDetailListener mCallback;
    // creates a Gesture Detector
    private GestureDetector gd;

    /*
     * (non-Javadoc)
     * @see
     * android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
     * android.view.ViewGroup, android.os.Bundle)
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        // If activity recreated (such as from screen rotate), restore
        // the previous article selection set by onSaveInstanceState().
        // This is primarily necessary when in the two-pane layout.
        if (savedInstanceState != null) {
            fileInformation = (FileInformation) savedInstanceState.get(FILEINFOMATION);
        }
        view = inflater.inflate(R.layout.product_detail, container, false);
        /* variables init */
        vv = (VideoView) view.findViewById(R.id.videoView1);
        vv.setOnTouchListener(this);

        imageView = (ImageView) view.findViewById(R.id.barcode_image);
        imageView.setOnTouchListener(this);
        // listeners for VideoView:
        vv.setOnErrorListener(this);
        vv.setOnPreparedListener(this);

        progress = (ProgressBar) view.findViewById(R.id.progressBar);
        loading = new ProgressDialog(getActivity());
        loading.setMessage("Loading...");
        // initialize the Gesture Detector
        gd = new GestureDetector(this);
        // set the on Double tap listener
        gd.setOnDoubleTapListener(new OnDoubleTapListener()
        {
            @Override
            public boolean onDoubleTap(MotionEvent e)
            {
                // set text color to green
                // print a confirmation message
                onDoubleTouchListener();
                return true;
            }

            @Override
            public boolean onDoubleTapEvent(MotionEvent e)
            {
                return false;
            }

            @Override
            public boolean onSingleTapConfirmed(MotionEvent e)
            {
                // set text color to red
                onSingleTouchListener();
                return true;
            }
        });

        // Inflate the layout for this fragment
        return view;
    }

    /**
     * Inits the media.
     * 
     * @param url the url
     */
    public void initMedia(String url) {
        loading.show();
        readyToPlay = false;
        stopMedia();
        // test
        // String uriString = "android.resource://" +
        // getActivity().getPackageName() + "/"
        // + jp.co.memory_tech.starchive.R.raw.video_1;
        // Uri uri = Uri.parse(uriString);
        // // end test
        Uri uri = Uri.parse(url);
        Log.d(this.getClass().getName(), "set media file to VideoView");
        vv.setVideoURI(uri);
        vv.requestFocus();
        // playMedia(null);
    }

    /*
     * (non-Javadoc)
     * @see android.support.v4.app.Fragment#onAttach(android.app.Activity)
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception.
        try {
            mCallback = (OnProductDetailListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }

    /*
     * (non-Javadoc)
     * @see android.support.v4.app.Fragment#onStart()
     */
    @Override
    public void onStart() {
        super.onStart();

        // During startup, check if there are arguments passed to the fragment.
        // onStart is a good place to do this because the layout has already
        // been
        // applied to the fragment at this point so we can safely call the
        // method
        // below that sets the article text.
        Bundle args = getArguments();
        if (args != null) {
            // Set article based on argument passed in
            updateProductDetail((FileInformation) args.get(FILEINFOMATION));
        }
    }

    /**
     * Update product detail.
     * 
     * @param position the position
     */
    public void updateProductDetail(FileInformation productItem) {
        if (productItem != null) {

            progress.setProgress(0);
            progress.setSecondaryProgress(0);
            ((TextView) getActivity().findViewById(R.id.filename_detail)).setText(getActivity()
                    .getString(
                            R.string.filename)
                    + ": " + productItem.getName());
            ((TextView) getActivity().findViewById(R.id.date_detail)).setText(getActivity()
                    .getString(
                            R.string.date_create)
                    + ": " + productItem.getCreateTime());
            ((TextView) getActivity().findViewById(R.id.tapeno_detail)).setText(getActivity()
                    .getString(
                            R.string.tapeno)
                    + ": " + productItem.getTapeNo());

            ((TextView) getActivity().findViewById(R.id.status)).setText(getActivity().getString(
                    R.string.status)
                    + ": " + productItem.getFileStatus());
            fileInformation = productItem;
            String filetype = productItem.getPreviewFile().substring(
                    productItem.getPreviewFile().lastIndexOf("."));
            Log.i("tamle", "filetype: " + filetype);
            if (filetype.trim().equalsIgnoreCase(".jpg")) {
                Log.i("tamle", "filetype: Image show");
                // the case of image file
                vv.setVisibility(View.GONE);
                imageView.setVisibility(View.VISIBLE);
                view.findViewById(R.id.progressBar).setVisibility(View.GONE);
                BitmapFactory.Options bmOptions;
                bmOptions = new BitmapFactory.Options();
                bmOptions.inSampleSize = 1;
                Bitmap bm = loadImage(productItem.getPreviewFile(), bmOptions);
                if (bm != null) {
                    imageView.setImageBitmap(bm);
                } else {
                    imageView.setVisibility(View.INVISIBLE);
                    Log.i("Tamle", "can't open image");
                }
            } else if (filetype.trim().equalsIgnoreCase(".pdf")) {
                Log.i("tamle", "filetype: pdf show");
                stopMedia();
                vv.setVisibility(View.GONE);
                imageView.setVisibility(View.GONE);
                view.findViewById(R.id.progressBar).setVisibility(View.GONE);
                return;
            } else {
                Log.i("tamle", "filetype: audio show");
                vv.setVisibility(View.VISIBLE);
                imageView.setVisibility(View.GONE);
                view.findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
                // stop media to prepare for new media
                stopMedia();
                // init media to play video
                initMedia(productItem.getPreviewFile());
            }
        }
    }

    /**
     * Load image from server
     * 
     * @author Tam-LT
     * @param imageFile the image file
     * @param bmOptions the bm options
     * @return the bitmap
     */
    private Bitmap loadImage(String imageFile, Options bmOptions) {
        // TODO Auto-generated method stub
        Bitmap bitmap = null;
        InputStream in = null;
        try {
            in = openHttpConnection(imageFile);
            // in = getActivity().getAssets().open("sample6.png");
            if (in != null) {
                bitmap = BitmapFactory.decodeStream(in, null, bmOptions);
                in.close();
            }
        } catch (IOException e1) {
        }
        return bitmap;
    }

    /**
     * Open http connection base on URL.
     * 
     * @author Tam-LT
     * @param imageFile the image file
     * @return the input stream
     * @throws IOException Signals that an I/O exception has occurred.
     */
    private InputStream openHttpConnection(String imageFile) throws IOException {
        InputStream inputStream = null;
        URL url = new URL(imageFile);
        URLConnection conn = url.openConnection();

        try {
            HttpURLConnection httpConn = (HttpURLConnection) conn;
            httpConn.setRequestMethod("GET");
            httpConn.setConnectTimeout(1000);
            httpConn.connect();

            if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                inputStream = httpConn.getInputStream();
            }
        } catch (Exception ex)
        {
        }
        return inputStream;
    }

    /*
     * (non-Javadoc)
     * @see
     * android.support.v4.app.Fragment#onSaveInstanceState(android.os.Bundle)
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // Save the current article selection in case we need to recreate the
        // fragment
        outState.putSerializable(FILEINFOMATION, fileInformation);
    }

    /**
     * Callback invoked when error occurs during buffering or playback.
     * 
     * @param player MediaPlayer which error refers to
     * @param what type of error
     * @param extra more specific information about the error
     * @return TRUE when method handled the error, FALSE if didn't
     */
    @Override
    public boolean onError(MediaPlayer player, int what, int extra) {
        loading.hide();
        return false;
    }

    /**
     * Callback invoked when media is ready for playback.
     * 
     * @param mp MediaPlayer that is ready
     */
    @Override
    public void onPrepared(MediaPlayer mp) {
        Log.d(this.getClass().getName(), "prepared");
        mp.setLooping(true);
        loading.hide();

        // video size check (media is a video if size is defined, audio if not)
        int h = mp.getVideoHeight();
        int w = mp.getVideoWidth();
        if (h != 0 && w != 0) {
            Log.d(this.getClass().getName(), "logo off");
        } else {
            Log.d(this.getClass().getName(), "logo on");
        }

        // onVideoSizeChangedListener declaration
        mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
            // video size check (media is a video if size is defined, audio if
            // not)
            @Override
            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                if (width != 0 && height != 0) {
                    Log.d(this.getClass().getName(), "logo off");
                } else {
                    Log.d(this.getClass().getName(), "logo on");
                }
            }
        });

        // onBufferingUpdateListener declaration
        mp.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
            // show updated information about the buffering progress
            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                Log.d(this.getClass().getName(), "percent: " + percent);
                progress.setSecondaryProgress(percent);
            }
        });

        mp.setOnCompletionListener(null);

        readyToPlay = true;
        int time = vv.getDuration();
        int time_elapsed = vv.getCurrentPosition();
        progress.setProgress(time_elapsed);

        // update current playback time every 500ms until stop
        timer = new CountDownTimer(time, 500) {

            @Override
            public void onTick(long millisUntilFinished) {
                // mediaTimeElapsed.setText(countTime(vv.getCurrentPosition()));
                float a = vv.getCurrentPosition();
                float b = vv.getDuration();
                progress.setProgress((int) (a / b * 100));
            }

            @Override
            public void onFinish() {
                stopMedia();
            }
        };

        // onTouchListener declaration
        progress.setOnTouchListener(new OnTouchListener() {

            // enables changing of the current playback position
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ProgressBar pb = (ProgressBar) v;

                int newPosition = (int) (100 * event.getX() / pb.getWidth());
                if (newPosition > pb.getSecondaryProgress()) {
                    newPosition = pb.getSecondaryProgress();
                }

                switch (event.getAction()) {
                // update position when finger is DOWN/MOVED/UP
                    case MotionEvent.ACTION_DOWN:
                    case MotionEvent.ACTION_MOVE:
                    case MotionEvent.ACTION_UP:
                        pb.setProgress(newPosition);
                        vv.seekTo(newPosition * vv.getDuration() / 100);
                        break;
                }
                return true;
            }
        });
        playMedia();
    }

    /**
     * Convert time from milliseconds into minutes and seconds, proper to media
     * player.
     * 
     * @param miliseconds media content time in milliseconds
     * @return time in format minutes:seconds
     */
    public String countTime(int miliseconds) {
        String timeInMinutes = new String();
        int minutes = miliseconds / 60000;
        int seconds = (miliseconds % 60000) / 1000;
        timeInMinutes = minutes + ":" + (seconds < 10 ? "0" + seconds : seconds);
        return timeInMinutes;
    }

    /**
     * Start or Pause playback of media content.
     * 
     * @param v View the touch event has been dispatched to
     */
    public void playMedia() {
        Log.i(tag, "playMedia");
        if (readyToPlay) {
            vv.start();
            timer.start();
        }
    }

    /**
     * Stop media.
     */
    public void stopMedia() {
        Log.i(tag, "stopMedia");
        if (vv != null && vv.getCurrentPosition() != 0) {
            vv.pause();
            vv.seekTo(0);
            timer.cancel();
            progress.setProgress(0);
            progress.setSecondaryProgress(0);
        }
    }

    /*
     * (non-Javadoc)
     * @see android.support.v4.app.Fragment#onStop()
     */
    @Override
    public void onStop() {
        super.onStop();
        Log.i(tag, "onStop");
        vv.stopPlayback();
        if (timer != null) {
            timer.cancel();
        }
        vv.setVideoURI(null);

    }

    /**
     * On key back.
     */
    public void onKeyBack() {
        // TODO Auto-generated method stub
        onStop();

    }

    @Override
    public void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        Log.i(tag, "onPause");
        vv.stopPlayback();
        // if (timer != null) {
        // timer.cancel();
        // }
        stopMedia();
        vv.setVideoURI(null);

    }

    @Override
    public void onSingleTouchListener() {
        // TODO Auto-generated method stub
        if (readyToPlay) {
            if (vv.isPlaying()) {
                vv.pause();
                timer.cancel();
                // view.findViewById(R.id.icon_play).setVisibility(View.VISIBLE);
            } else {
                // view.findViewById(R.id.icon_play).setVisibility(View.GONE);
                vv.start();
                timer.start();
            }
        }
    }

    @Override
    public void onDoubleTouchListener() {
        // TODO Auto-generated method stub
        Log.i(tag, "double tap on video view");
        isFullScreen = !isFullScreen;
        mCallback.onShowFullScreenVideo(isFullScreen);

    }

    /**
     * Hide description.
     */
    public void hideDescription() {
        // TODO Auto-generated method stub
        view.findViewById(R.id.product_description).setVisibility(View.GONE);

    }

    public void showDescription() {
        // TODO Auto-generated method stub
        view.findViewById(R.id.product_description).setVisibility(View.VISIBLE);

    }

    @Override
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        gd.onTouchEvent(event);
        return true;
    }

}
